﻿using System;
using System.Collections.Generic;
using Plugins.Interfaces;

namespace Plugins.Core
{
    [Serializable]
    public class PluginDequeueCollection<T> : List<T>,  IPluginDequeueCollection<T>
    {
        #region Members
        int mIndex = -1;
        #endregion
        #region Constructors
        public PluginDequeueCollection() { }
        public PluginDequeueCollection(int capacity)
        {
            for (int i = 0; i < capacity; i++)
            {
                base.Add(default(T));
            }
        }
        public PluginDequeueCollection(IEnumerable<T> items) : base(items)
        {
        }
        #endregion
        #region Functions
        public bool CanMovePrevious(int index)
        {
            return index > -1;
        }
        public bool CanMoveNext(int index)
        {
            return index < base.Count;
        }
        #endregion
        #region IDequeue<T> Members
        public void AddFirst(T value)
        {
            base.Insert(0, value);
        }
        public void AddLast(T value)
        {
            base.Insert(base.Count, value);
        }
        public bool RemoveFirst()
        {
            if (base.Count > 0)
            {
                base.RemoveAt(0);
                return true;
            }
            return false;
        }
        public bool RemoveLast()
        {
            if (base.Count > 0)
            {
                base.RemoveAt(base.Count - 1);
                return true;
            }
            return false;
        }
        public void AddFirstLastOut(T value, int capacity)
        {
            AddFirst(value);
            Resize(Direction.Tail, capacity);
        }
        public void AddLastFirstOut(T value, int capacity)
        {
            AddLast(value);
            Resize(Direction.Head, capacity);
        }
        public void AddFirstLastCenterOut(T head, T tail)
        {
            int center = (base.Count + 1) / 2;
            AddFirst(head);
            AddLast(tail);
            base.RemoveAt(center);
            base.RemoveAt(center);
        }
        public void Resize(Direction direction, int capacity)
        {
            switch (direction)
            {
                case Direction.Head:
                    while (base.Count > capacity)
                    {
                        RemoveFirst();
                    }
                    while (base.Count < capacity)
                    {
                        AddFirst(default(T));
                    }
                    break;
                case Direction.Tail:
                    while (base.Count > capacity)
                    {
                        RemoveLast();
                    }
                    while (base.Count < capacity)
                    {
                        AddLast(default(T));
                    }
                    break;
                default:
                    throw new NotImplementedException();
            }
        }
        public T PreviousItem
        {
            get
            {
                if (CanMovePrevious(mIndex - 1))
                    return base[mIndex - 1];
                return Current;
            }
        }
        public T NextItem
        {
            get
            {
                if (CanMoveNext(mIndex + 1))
                    return base[mIndex + 1];
                return Current;
            }
        }
        #endregion
        #region IEnumerator<T> Members
        public void Reset()
        {
            mIndex = -1;
        }
        public T Current
        {
            get
            {
                if (CanMovePrevious(mIndex) && CanMoveNext(mIndex))
                {
                    return base[mIndex];
                }
                return default(T);
            }
        }
        public int Position
        {
            get
            {
                return mIndex;
            }
        }
        public bool MovePrevious()
        {
            if (CanMovePrevious(mIndex))
            {
                return --mIndex == -1;
            }
            return false;
        }
        public bool MoveNext()
        {
            if (CanMoveNext(mIndex))
            {
                return ++mIndex == base.Count;
            }
            return false;
        }
        #endregion
        #region ICollection<T> Members
        void ICollection<T>.Add(T item)
        {
            base.Add(item);
        }
        bool ICollection<T>.Remove(T item)
        {
            return base.Remove(item);
        }
        #endregion
        #region IList<T> Members
        public bool IsFixedSize
        {
            get { return false; }
        }
        public bool IsReadOnly
        {
            get { return false; }
        }
        #endregion
    }
}
